package meta

import (
	"log"
	"moss/conf"
)

type Object struct {
	ID               uint   `gorm:"primary_key"`
	BucketName       string `gorm:"not null"`
	Key              string `gorm:"not null"`
	LastModified     string `gorm:"not null"`
	ETag             string `gorm:"not null"`
	Type             string `gorm:"not null"`
	Size             int64  `gorm:"not null"`
	StorageClass     string `gorm:"not null"`
	FileLocation     string `gorm:"not null"`
	OwnerAccessKeyId string `gorm:"not null"`
	Permission       string `gorm:"not null"`
	Encryption       string
	SymlinkTarget    string
	UserMeta         string
	Crc64Checksum    string
	AESPrivateKey    string
}

func InitObjectInfo() {
	if !dbHook.HasTable(&Object{}) {
		dbHook.CreateTable(&Object{})
	}
}

func SetObjectInfo(bucketName, key, accessKeyId, tag, fileLocation, permission, encryption, objectType, symlinkTarget, userMeta, crc, lastModified string, size int64) *Object {
	var objectMeta Object
	entry, ok := GetObjectInfo(bucketName, key)
	if ok {
		entry.LastModified = lastModified //time.Now().Format(time.RFC3339)
		entry.ETag = tag
		entry.Size = size
		entry.FileLocation = fileLocation
		entry.OwnerAccessKeyId = accessKeyId
		entry.Permission = permission
		entry.Encryption = encryption
		entry.Type = objectType
		entry.SymlinkTarget = symlinkTarget
		entry.UserMeta = userMeta
		entry.Crc64Checksum = crc
		dbHook.Save(entry)
		objectMeta = *entry
	} else {
		objectMeta.BucketName = bucketName
		objectMeta.Key = key
		objectMeta.LastModified = lastModified // time.Now().Format(time.RFC3339)
		objectMeta.ETag = tag
		objectMeta.Type = objectType
		objectMeta.Size = size
		objectMeta.StorageClass = conf.ObjectStorageClassStandard
		objectMeta.FileLocation = fileLocation
		objectMeta.OwnerAccessKeyId = accessKeyId
		objectMeta.Permission = permission
		objectMeta.Encryption = encryption
		objectMeta.SymlinkTarget = symlinkTarget
		objectMeta.UserMeta = userMeta
		objectMeta.Crc64Checksum = crc
		dbHook.Create(&objectMeta)
	}
	return &objectMeta
}

func GetObjectInfo(bucketName string, key string) (*Object, bool) {
	var objectMeta Object
	resp := dbHook.Find(&objectMeta, "bucket_name = ? and key = ?", bucketName, key)
	if resp.RecordNotFound() {
		return nil, false
	}

	return &objectMeta, true
}

func GetAllObjects(bucketName string, prefix string) []Object {
	var objectList []Object
	resp := dbHook.Where("bucket_name = ? and key like ?", bucketName, prefix+"%").Find(&objectList)
	if resp.RecordNotFound() {
		return nil
	}

	return objectList
}

func DeleteObject(bucketName string, key string) bool {
	resp := dbHook.Delete(Object{}, "bucket_name = ? and key = ?", bucketName, key)
	if resp.RecordNotFound() {
		return false
	}
	if resp.Error != nil {
		return false
	}

	return true
}

func SetObjectPermission(objectMeta *Object, newPermission string) bool {
	resp := dbHook.Model(objectMeta).Update("permission", newPermission)
	if resp.Error != nil {
		log.Println(resp.Error.Error())
		return false
	}
	return true
}
